﻿using Common.Exceptions;
using Microsoft.Extensions.Configuration;
using System;
using System.Text.RegularExpressions;

namespace Extensions.Configuration
{
    /// <summary>
    /// 配置快速操作方法
    /// </summary>
    public static class ConfigurationFastOperationFunctions
    {
        /// <summary>
        /// 获取boolean型配置
        /// <para>未找到配置时返回false</para>
        /// <para>配置为true/false，直接转换返回</para>
        /// <para>配置为数字的，一切非零的数字都为true</para>
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name"></param>
        /// <returns>未找到配置时返回false</returns>
        public static bool GetBoolean(this IConfiguration configuration, string name)
        {
            string val = configuration[name];
            if (string.IsNullOrEmpty(val))
            {
                return false;
            }
            if (Regex.IsMatch(val, "^-?\\d+(\\.\\d+)?$"))
            {
                //一切非零的数字都为true
                return !"0".Equals(val);
            }
            return "true".Equals(val, StringComparison.OrdinalIgnoreCase);
        }
        /// <summary>
        /// 获取可空的布尔类型配置，找不到或配置无效时，返回默认值
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name">配置名称</param>
        /// <param name="defaultValue">找不到或配置无效时的默认值</param>
        /// <returns></returns>
        public static bool? GetBoolean(this IConfiguration configuration, string name, bool? defaultValue)
        {
            string temp = configuration.GetString(name);
            if (!bool.TryParse(temp, out bool val))
            {
                return defaultValue;
            }
            return val;
        }
        /// <summary>
        /// 获取字符串型配置
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static string GetString(this IConfiguration configuration, string name)
        {
            return configuration[name];
        }
        /// <summary>
        /// 获取长整型配置，未找到配置或配置格式不正确，异常<see cref="MissingConfigurationException"/>或<see cref="InvalidConfigurationException"/>
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name">配置名称，允许使用多级配置</param>
        /// <exception cref="MissingConfigurationException">未找到配置项</exception>
        /// <exception cref="InvalidConfigurationException">配置值无效</exception>
        /// <returns></returns>
        public static long GetLong(this IConfiguration configuration, string name)
        {
            string val = configuration.GetString(name);
            if (string.IsNullOrEmpty(val))
            {
                throw new MissingConfigurationException(name);
            }
            if (!long.TryParse(val, out long res))
            {
                throw new InvalidConfigurationException(name, val);
            }
            return res;
        }
        /// <summary>
        /// 获取长整型配置，未找到配置或配置格式不正确，返回指定默认值
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name">配置名称</param>
        /// <param name="defaultVal">未找到配置或配置不正确时的默认值</param>
        /// <returns></returns>
        public static long GetLong(this IConfiguration configuration, string name, long defaultVal)
        {
            string val = configuration.GetString(name);
            if (!long.TryParse(val, out long res))
            {
                return defaultVal;
            }
            return res;
        }
        /// <summary>
        /// 获取长整型配置，未找到配置或配置格式不正确，返回null
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name"></param>
        /// <param name="defaultVal">找不到或配置无效时的默认值，允许null</param>
        /// <returns></returns>
        public static long? GetLong(this IConfiguration configuration, string name, long? defaultVal)
        {
            string val = configuration.GetString(name);
            if (!long.TryParse(val, out long res))
            {
                return defaultVal;
            }
            return res;
        }
        /// <summary>
        /// 获取整数型配置，未找到或配置不正确时，抛出异常
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name"></param>
        /// <exception cref="MissingConfigurationException">未找到配置项</exception>
        /// <exception cref="InvalidConfigurationException">配置值无效</exception>
        /// <returns></returns>
        public static int GetInt(this IConfiguration configuration, string name)
        {
            string temp = configuration.GetString(name);
            if (string.IsNullOrEmpty(temp))
            {
                throw new MissingConfigurationException(name);
            }
            if (!int.TryParse(configuration.GetString(name), out int val))
            {
                throw new InvalidConfigurationException(name, temp);
            }
            return val;
        }
        /// <summary>
        /// 获取整数型配置，未找到或配置不正确时，抛出异常
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name"></param>
        /// <param name="defaultVal">找不到配置或配置无效时的默认值</param>
        /// <exception cref="MissingConfigurationException">未找到配置项</exception>
        /// <exception cref="InvalidConfigurationException">配置值无效</exception>
        /// <returns></returns>
        public static int GetInt(this IConfiguration configuration, string name, int defaultVal)
        {
            try
            {
                return configuration.GetInt(name);
            }
            catch
            {
                return defaultVal;
            }
        }
        /// <summary>
        /// 获取整数型配置，未找到或配置不正确时，返回null
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name"></param>
        /// <param name="defaultVal">找不到或配置无效时的默认值，允许null</param>
        /// <exception cref="MissingConfigurationException">未找到配置项</exception>
        /// <exception cref="InvalidConfigurationException">配置值无效</exception>
        /// <returns></returns>
        public static int? GetInt(this IConfiguration configuration, string name, int? defaultVal)
        {
            string temp = configuration.GetString(name);
            if (!int.TryParse(temp, out int val))
            {
                return defaultVal;
            }
            return val;
        }
        /// <summary>
        /// 获取时间类型的配置，未找到配置或配置无效时，抛出异常
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name">配置名称</param>
        /// <exception cref="MissingConfigurationException">未找到配置</exception>
        /// <exception cref="InvalidConfigurationException">无效的配置值</exception>
        /// <returns></returns>
        public static DateTime GetDateTime(this IConfiguration configuration, string name)
        {
            string temp = configuration.GetString(name);
            if (string.IsNullOrEmpty(temp))
            {
                throw new MissingConfigurationException(name);
            }
            if (!DateTime.TryParse(temp, out DateTime val))
            {
                throw new InvalidConfigurationException(name, temp);
            }
            return val;
        }
        /// <summary>
        /// 获取时间类型的配置，未找到配置或配置无效时，返回默认值
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name">配置名称</param>
        /// <param name="defaultVal">找不到或配置无效时的默认值，允许null</param>
        /// <exception cref="MissingConfigurationException">未找到配置</exception>
        /// <exception cref="InvalidConfigurationException">无效的配置值</exception>
        /// <returns></returns>
        public static DateTime GetDateTime(this IConfiguration configuration, string name, DateTime defaultVal)
        {
            try
            {
                return configuration.GetDateTime(name);
            }
            catch
            {
                return defaultVal;
            }
        }
        /// <summary>
        /// 获取时间类型的配置，未找到配置或配置无效时，返回默认值
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name">配置名称</param>
        /// <param name="defaultVal">找不到或配置无效时的默认值，允许null</param>
        /// <exception cref="MissingConfigurationException">未找到配置</exception>
        /// <exception cref="InvalidConfigurationException">无效的配置值</exception>
        /// <returns></returns>
        public static DateTime? GetDateTime(this IConfiguration configuration, string name, DateTime? defaultVal)
        {
            try
            {
                return configuration.GetDateTime(name);
            }
            catch
            {
                return defaultVal;
            }
        }
        /// <summary>
        /// 获取金额数据类型的配置，未找到配置或配置无效时，抛出异常
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name">配置名称</param>
        /// <exception cref="MissingConfigurationException">未找到配置</exception>
        /// <exception cref="InvalidConfigurationException">无效的配置值</exception>
        /// <returns></returns>
        public static decimal GetDecimal(this IConfiguration configuration, string name)
        {
            string temp = configuration.GetString(name);
            if (string.IsNullOrEmpty(temp))
            {
                throw new MissingConfigurationException(name);
            }
            if (!decimal.TryParse(temp, out decimal res))
            {
                throw new InvalidConfigurationException(name, temp);
            }
            return res;
        }
        /// <summary>
        /// 获取金额数据类型的配置，未找到配置或配置无效时，返回默认值
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name">配置名称</param>
        /// <param name="defaultVal">找不到或配置无效时的默认值</param>
        /// <exception cref="MissingConfigurationException">未找到配置</exception>
        /// <exception cref="InvalidConfigurationException">无效的配置值</exception>
        /// <returns></returns>
        public static decimal GetDecimal(this IConfiguration configuration, string name, decimal defaultVal)
        {
            try
            {
                return configuration.GetDecimal(name);
            }
            catch
            {
                return defaultVal;
            }
        }
        /// <summary>
        /// 获取金额数据类型的配置，未找到配置或配置无效时，返回默认值
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="name">配置名称</param>
        /// <param name="defaultVal">找不到或配置无效时的默认值，允许null</param>
        /// <exception cref="MissingConfigurationException">未找到配置</exception>
        /// <exception cref="InvalidConfigurationException">无效的配置值</exception>
        /// <returns></returns>
        public static decimal? GetDecimal(this IConfiguration configuration, string name, decimal? defaultVal)
        {
            try
            {
                return configuration.GetDecimal(name);
            }
            catch
            {
                return defaultVal;
            }
        }
    }
}
